# Gitee Contribution Box GUI应用
import sys
import os
import urllib
import urllib.request
import io
import threading
import smtplib
import re
import tempfile
from bs4 import BeautifulSoup
from PIL import Image, ImageDraw, ImageFont
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.utils import formataddr
from html2image import Html2Image
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QLabel, QLineEdit, QPushButton, QTextEdit, QGroupBox, 
                             QFormLayout, QMessageBox, QFileDialog, QTabWidget, QSplitter,
                             QFrame, QProgressBar, QStatusBar)
from PyQt5.QtGui import QPixmap, QFont, QIcon, QColor, QPalette, QImage
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QSize, QBuffer
from PyQt5.QtSvg import QSvgRenderer

# 定义颜色方案
COLORS = {
    'primary': '#3498db',    # 蓝色
    'secondary': '#2ecc71',   # 绿色
    'accent': '#e74c3c',      # 红色
    'light': '#ecf0f1',       # 浅灰色
    'dark': '#2c3e50',        # 深蓝灰色
    'text': '#34495e',        # 文本颜色
    'background': '#f9f9f9'   # 背景色
}

# 工作线程类 - 用于后台处理网络请求和邮件发送
class WorkerThread(QThread):
    update_signal = pyqtSignal(str)
    image_signal = pyqtSignal(bytes)
    finished_signal = pyqtSignal(bool, str)
    progress_signal = pyqtSignal(int)
    
    def __init__(self, gitee_url, email_config=None):
        super().__init__()
        self.gitee_url = gitee_url
        self.email_config = email_config
        self.img_data = None
        self.contribution_text = ""
        
    def parse_contribution_data(self, contribution_box):
        """解析贡献数据"""
        contribution_data = {
            'boxes': [],
            'total': 0,
            'max_contributions': 0,
            'months': []
        }
        
        # 查找所有贡献方块
        boxes = contribution_box.find_all('div', class_='box')
        for box in boxes:
            # 获取日期和贡献数量
            date = box.get('date', '')
            count = 0
            data_content = box.get('data-content', '')
            if data_content:
                # 从data-content中提取贡献数量
                count_match = re.search(r'(\d+)\s+次提交', data_content)
                if count_match:
                    count = int(count_match.group(1))
                    contribution_data['total'] += count
                    contribution_data['max_contributions'] = max(contribution_data['max_contributions'], count)
            
            # 添加到贡献数据中
            contribution_data['boxes'].append({
                'date': date,
                'count': count
            })
        
        # 查找月份标签
        month_labels = contribution_box.find_all('div', class_='month')
        for month in month_labels:
            contribution_data['months'].append(month.get_text(strip=True))
        
        return contribution_data
    
    def draw_contribution_heatmap(self, draw, contribution_data, img_width, img_height, font):
        """绘制贡献热力图"""
        # 热力图区域
        heatmap_x = 20
        heatmap_y = 100
        heatmap_width = img_width - 40
        heatmap_height = 120
        
        # 计算方块大小和间距
        box_size = 10
        box_margin = 2
        max_boxes_per_row = min(53, len(contribution_data['boxes']) // 7 + 1)  # 最多53周
        max_boxes_per_col = 7  # 一周7天
        
        # 绘制月份标签
        month_width = heatmap_width / len(contribution_data['months'])
        for i, month in enumerate(contribution_data['months']):
            x = heatmap_x + i * month_width
            draw.text((x, heatmap_y - 20), month, fill=(255, 255, 255), font=font)
        
        # 绘制星期标签
        weekdays = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
        for i, day in enumerate(weekdays):
            y = heatmap_y + i * (box_size + box_margin)
            draw.text((heatmap_x - 30, y), day, fill=(255, 255, 255), font=font)
        
        # 绘制贡献方块
        boxes = contribution_data['boxes']
        max_contrib = max(1, contribution_data['max_contributions'])  # 避免除以零
        
        for i, box_data in enumerate(boxes):
            # 计算位置
            week = i // 7
            day = i % 7
            
            if week >= max_boxes_per_row:
                continue
            
            x = heatmap_x + week * (box_size + box_margin)
            y = heatmap_y + day * (box_size + box_margin)
            
            # 计算颜色强度（基于贡献数量）
            count = box_data['count']
            if count == 0:
                color = (220, 220, 220)  # 浅灰色表示无贡献
            else:
                # 绿色渐变，贡献越多颜色越深
                intensity = min(1.0, count / max_contrib)
                green = int(220 - intensity * 170)  # 从浅绿到深绿
                color = (0, green, 0)
            
            # 绘制方块
            draw.rectangle([(x, y), (x + box_size, y + box_size)], fill=color, outline=None)
        
    def html_to_image(self, html_content, css=None):
        """将HTML内容转换为图像"""
        try:
            # 创建临时目录用于存放临时文件
            temp_dir = tempfile.mkdtemp(prefix="gitee_contribution_")
            
            # 创建Html2Image实例
            hti = Html2Image(output_path=temp_dir)
            
            # 设置截图大小，确保能够完整捕获贡献图表
            hti.size = (1000, 500)
            
            # 添加CSS样式，确保贡献图表正确显示
            if css is None:
                css = """
                body {
                     background-color: white;
                     margin: 0;
                     padding: 20px;
                     font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
                 }
                 .container {
                     max-width: 980px;
                     margin: 0 auto;
                     padding: 0 15px;
                 }
                .contribution-box {
                    display: block;
                    background-color: white;
                    padding: 10px;
                    border-radius: 6px;
                    overflow: hidden;
                    margin-bottom: 20px;
                    width: 100%;
                }
                .box {
                    display: inline-block;
                    width: 10px;
                    height: 10px;
                    margin: 1px;
                    background-color: #f6f8fa !important;
                    border: 1px solid rgba(27, 31, 35, 0.06);
                }
                .box:hover {
                    border: none !important;
                }
                .box.less {
                    background-color: #ebedf0 !important;
                }
                .box.little {
                    background-color: #9be9a8 !important;
                }
                .box.more {
                    background-color: #40c463 !important;
                }
                .box.most {
                    background-color: #30a14e !important;
                }
                .contribution-describ {
                    margin-top: 10px;
                    font-size: 14px;
                    color: #24292e;
                }
                """
            
            # 创建完整的HTML文档
            full_html = f"""
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Gitee Contribution</title>
                <style>
                    {css}
                </style>
            </head>
            <body>
                <div class="container">
                    {html_content}
                    <div class="contribution-describ">
                        <p>{self.contribution_text}</p>
                    </div>
                </div>
            </body>
            </html>
            """
            
            # 截图并获取图像路径
            screenshot_path = hti.screenshot(html_str=full_html, save_as="contribution_box.png")[0]
            
            # 读取图像文件
            with open(screenshot_path, "rb") as f:
                img_data = f.read()
            
            # 清理临时文件
            os.remove(screenshot_path)
            os.rmdir(temp_dir)
            
            return img_data
        except Exception as e:
            self.update_signal.emit(f"HTML转图像失败: {str(e)}")
            return None
    
    def run(self):
        try:
            # 更新进度
            self.progress_signal.emit(10)
            self.update_signal.emit("正在获取网页内容...")
            
            # 获取网页内容
            with urllib.request.urlopen(self.gitee_url) as response:
                info = ""
                for line in response:
                    line = line.decode()
                    info += line + "\n"
            
            # 更新进度
            self.progress_signal.emit(30)
            self.update_signal.emit("正在解析HTML内容...")
            
            # 使用BeautifulSoup解析HTML
            soup = BeautifulSoup(info, 'html.parser')
            
            # 查找contribution-box类的元素
            contribution_box = soup.find(class_="contribution-box")
            
            if contribution_box:
                # 更新进度
                self.progress_signal.emit(50)
                self.update_signal.emit("正在生成图像...")
                
                # 解析贡献数据以获取总贡献数
                contribution_data = self.parse_contribution_data(contribution_box)
                self.contribution_text = f"最近一年贡献: {contribution_data['total']} 次"
                self.update_signal.emit(f"找到contribution-box: {self.contribution_text}")
                
                # 直接将HTML转换为图像
                contribution_html = str(contribution_box)
                self.update_signal.emit("正在将HTML转换为图像...")
                
                # 使用html2image将HTML转换为图像
                img_data = self.html_to_image(contribution_html)
                
                if img_data:
                    # 保存图像内容供邮件使用
                    self.img_data = img_data
                    
                    # 发送图像信号
                    self.image_signal.emit(self.img_data)
                    
                    # 如果配置了邮件，则发送邮件
                    if self.email_config:
                        # 更新进度
                        self.progress_signal.emit(70)
                        self.update_signal.emit("正在准备发送邮件...")
                        
                        # 发送邮件
                        self.send_email()
                    else:
                        self.progress_signal.emit(100)
                        self.finished_signal.emit(True, "图像生成成功！")
                else:
                    # 如果HTML转图像失败，回退到原来的方法
                    self.update_signal.emit("HTML转图像失败，使用备用方法...")
                    
                    # 将contribution-box内容转换为图像
                    img_width, img_height = 600, 300
                    img = Image.new('RGB', (img_width, img_height), color=(255, 255, 255))
                    draw = ImageDraw.Draw(img)
                    
                    # 添加渐变背景
                    for y in range(img_height):
                        r = int(41 + (52 - 41) * y / img_height)
                        g = int(128 + (152 - 128) * y / img_height)
                        b = int(185 + (219 - 185) * y / img_height)
                        for x in range(img_width):
                            draw.point((x, y), fill=(r, g, b))
                    
                    # 尝试使用系统字体
                    try:
                        title_font = ImageFont.truetype("arial.ttf", 24)
                        content_font = ImageFont.truetype("arial.ttf", 18)
                        small_font = ImageFont.truetype("arial.ttf", 12)
                    except IOError:
                        title_font = ImageFont.load_default()
                        content_font = ImageFont.load_default()
                        small_font = ImageFont.load_default()
                    
                    # 在图像上绘制标题和贡献总数
                    draw.text((20, 20), "Gitee Contribution Box", fill=(255, 255, 255), font=title_font)
                    draw.text((20, 60), self.contribution_text, fill=(255, 255, 255), font=content_font)
                    
                    # 绘制贡献热力图
                    self.draw_contribution_heatmap(draw, contribution_data, img_width, img_height, small_font)
                    
                    # 添加边框
                    draw.rectangle([(10, 10), (img_width-10, img_height-10)], outline=(255, 255, 255), width=2)
                    
                    # 保存图像到内存中
                    img_byte_arr = io.BytesIO()
                    img.save(img_byte_arr, format='PNG')
                    img_byte_arr.seek(0)
                    
                    # 保存图像内容供邮件使用
                    self.img_data = img_byte_arr.getvalue()
                    
                    # 发送图像信号
                    self.image_signal.emit(self.img_data)
                    
                    # 如果配置了邮件，则发送邮件
                    if self.email_config:
                        # 更新进度
                        self.progress_signal.emit(70)
                        self.update_signal.emit("正在准备发送邮件...")
                        
                        # 发送邮件
                        self.send_email()
                    else:
                        self.progress_signal.emit(100)
                        self.finished_signal.emit(True, "图像生成成功！")
            else:
                self.update_signal.emit("未找到contribution-box类元素")
                self.finished_signal.emit(False, "未找到contribution-box类元素")
        except Exception as e:
            self.update_signal.emit(f"发生错误: {str(e)}")
            self.finished_signal.emit(False, f"发生错误: {str(e)}")
    
    def send_email(self):
        try:
            # 配置邮箱参数
            mail_host = self.email_config.get('mail_host', "smtp.qq.com")
            mail_port = self.email_config.get('mail_port', 587)
            sender_name = self.email_config.get('sender_name', "")
            sender = self.email_config.get('sender', "")
            password = self.email_config.get('password', "")
            receivers = self.email_config.get('receivers', "")
            
            # 构建符合RFC标准的邮件 - 使用多部分邮件
            msg = MIMEMultipart()
            msg["From"] = formataddr((sender_name, sender))
            msg["To"] = receivers
            msg["Subject"] = "Gitee Contribution Box 图像"
            
            # 添加HTML正文
            html_part = MIMEText("<h1>Gitee Contribution Box</h1><p>以下是您的Gitee贡献图表：</p>", "html", "utf-8")
            msg.attach(html_part)
            
            # 如果成功生成了图像，添加到邮件中
            if self.img_data:
                img_attachment = MIMEImage(self.img_data)
                img_attachment.add_header('Content-Disposition', 'attachment', filename='contribution_box.png')
                img_attachment.add_header('Content-ID', '<contribution_image>')
                msg.attach(img_attachment)
                
                # 添加引用图像的HTML
                img_html = MIMEText('<p><img src="cid:contribution_image"></p>', 'html')
                msg.attach(img_html)
            
            # 更新进度
            self.progress_signal.emit(85)
            self.update_signal.emit("正在发送邮件...")
            
            # 发送邮件
            with smtplib.SMTP(mail_host, mail_port) as server:
                server.starttls()
                server.login(sender, password)
                server.sendmail(sender, receivers, msg.as_string())
                
                # 检查连接状态
                response = server.noop()[1]
                if "250" in response.decode():
                    self.update_signal.emit("邮件确认已送达服务器")
                    self.progress_signal.emit(100)
                    self.finished_signal.emit(True, "邮件发送成功！")
                else:
                    self.update_signal.emit(f"服务器响应: {response}")
                    self.progress_signal.emit(100)
                    self.finished_signal.emit(True, "邮件已发送，但未收到确认")
        except Exception as e:
            self.update_signal.emit(f"邮件发送失败: {str(e)}")
            self.progress_signal.emit(100)
            self.finished_signal.emit(False, f"邮件发送失败: {str(e)}")

# 主窗口类
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Gitee Contribution Box")
        self.setMinimumSize(800, 600)
        self.img_data = None
        
        # 设置应用图标
        self.setup_icon()
        
        # 设置应用样式
        self.setup_style()
        
        # 初始化UI
        self.init_ui()
    
    def setup_icon(self):
        # 设置应用图标
        icon_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon.svg")
        if os.path.exists(icon_path):
            app_icon = QIcon(icon_path)
            self.setWindowIcon(app_icon)
    
    def setup_style(self):
        # 设置应用全局样式
        self.setStyleSheet(f"""
            QMainWindow, QWidget {{
                background-color: {COLORS['background']};
                color: {COLORS['text']};
            }}
            QLabel {{
                color: {COLORS['text']};
            }}
            QPushButton {{
                background-color: {COLORS['primary']};
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
                font-weight: bold;
            }}
            QPushButton:hover {{
                background-color: #2980b9;
            }}
            QPushButton:pressed {{
                background-color: #1f6aa5;
            }}
            QPushButton#secondary {{
                background-color: {COLORS['secondary']};
            }}
            QPushButton#secondary:hover {{
                background-color: #27ae60;
            }}
            QPushButton#secondary:pressed {{
                background-color: #1e8449;
            }}
            QPushButton#danger {{
                background-color: {COLORS['accent']};
            }}
            QPushButton#danger:hover {{
                background-color: #c0392b;
            }}
            QPushButton#danger:pressed {{
                background-color: #a93226;
            }}
            QLineEdit, QTextEdit {{
                border: 1px solid #bdc3c7;
                border-radius: 4px;
                padding: 8px;
                background-color: white;
            }}
            QGroupBox {{
                border: 1px solid #bdc3c7;
                border-radius: 4px;
                margin-top: 1em;
                padding-top: 10px;
            }}
            QGroupBox::title {{
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 3px 0 3px;
                color: {COLORS['primary']};
                font-weight: bold;
            }}
            QTabWidget::pane {{
                border: 1px solid #bdc3c7;
                border-radius: 4px;
            }}
            QTabBar::tab {{
                background-color: #ecf0f1;
                border: 1px solid #bdc3c7;
                border-bottom: none;
                border-top-left-radius: 4px;
                border-top-right-radius: 4px;
                padding: 8px 12px;
                margin-right: 2px;
            }}
            QTabBar::tab:selected {{
                background-color: {COLORS['primary']};
                color: white;
            }}
            QProgressBar {{
                border: 1px solid #bdc3c7;
                border-radius: 4px;
                text-align: center;
            }}
            QProgressBar::chunk {{
                background-color: {COLORS['primary']};
                width: 10px;
                margin: 0.5px;
            }}
        """)
    
    def init_ui(self):
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(20, 20, 20, 20)
        main_layout.setSpacing(15)
        
        # 创建标题标签
        title_label = QLabel("Gitee Contribution Box")
        title_label.setAlignment(Qt.AlignCenter)
        title_font = title_label.font()
        title_font.setPointSize(16)
        title_font.setBold(True)
        title_label.setFont(title_font)
        title_label.setStyleSheet(f"color: {COLORS['primary']};")
        main_layout.addWidget(title_label)
        
        # 创建标签页
        tab_widget = QTabWidget()
        main_layout.addWidget(tab_widget)
        
        # 创建主要功能标签页
        main_tab = QWidget()
        tab_widget.addTab(main_tab, "主页")
        
        # 创建设置标签页
        settings_tab = QWidget()
        tab_widget.addTab(settings_tab, "设置")
        
        # 设置主页标签页布局
        self.setup_main_tab(main_tab)
        
        # 设置设置标签页布局
        self.setup_settings_tab(settings_tab)
        
        # 创建状态栏
        self.statusBar = QStatusBar()
        self.setStatusBar(self.statusBar)
        self.statusBar.showMessage("就绪")
        
        # 创建进度条
        self.progress_bar = QProgressBar()
        self.progress_bar.setRange(0, 100)
        self.progress_bar.setValue(0)
        self.progress_bar.setTextVisible(True)
        self.progress_bar.setFixedHeight(15)
        self.statusBar.addPermanentWidget(self.progress_bar, 1)
    
    def setup_main_tab(self, tab):
        # 主页标签页布局
        layout = QVBoxLayout(tab)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(10)
        
        # 创建输入区域
        input_group = QGroupBox("输入")
        input_layout = QFormLayout(input_group)
        
        # Gitee URL输入
        self.url_input = QLineEdit("https://gitee.com/top_xiong")
        input_layout.addRow("Gitee URL:", self.url_input)
        
        layout.addWidget(input_group)
        
        # 创建按钮区域
        button_layout = QHBoxLayout()
        
        # 获取按钮
        self.fetch_button = QPushButton("获取贡献图表")
        self.fetch_button.clicked.connect(self.fetch_contribution)
        button_layout.addWidget(self.fetch_button)
        
        # 发送邮件按钮
        self.send_button = QPushButton("发送到邮箱")
        self.send_button.setObjectName("secondary")
        self.send_button.clicked.connect(self.send_email)
        self.send_button.setEnabled(False)
        button_layout.addWidget(self.send_button)
        
        # 保存图像按钮
        self.save_button = QPushButton("保存图像")
        self.save_button.clicked.connect(self.save_image)
        self.save_button.setEnabled(False)
        button_layout.addWidget(self.save_button)
        
        layout.addLayout(button_layout)
        
        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        layout.addWidget(splitter, 1)
        
        # 创建图像预览区域
        preview_group = QGroupBox("预览")
        preview_layout = QVBoxLayout(preview_group)
        
        self.image_label = QLabel("[图像预览区域]")
        self.image_label.setAlignment(Qt.AlignCenter)
        self.image_label.setMinimumHeight(200)
        self.image_label.setStyleSheet(f"background-color: {COLORS['light']}; border-radius: 4px;")
        preview_layout.addWidget(self.image_label)
        
        splitter.addWidget(preview_group)
        
        # 创建日志区域
        log_group = QGroupBox("日志")
        log_layout = QVBoxLayout(log_group)
        
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        log_layout.addWidget(self.log_text)
        
        splitter.addWidget(log_group)
        
        # 设置分割器初始大小
        splitter.setSizes([300, 100])
    
    def setup_settings_tab(self, tab):
        # 设置标签页布局
        layout = QVBoxLayout(tab)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(10)
        
        # 创建邮箱设置区域
        email_group = QGroupBox("邮箱设置")
        email_layout = QFormLayout(email_group)
        
        # 邮箱服务器设置
        self.mail_host_input = QLineEdit("smtp.qq.com")
        email_layout.addRow("邮箱服务器:", self.mail_host_input)
        
        self.mail_port_input = QLineEdit("587")
        email_layout.addRow("端口:", self.mail_port_input)
        
        # 发件人设置
        self.sender_name_input = QLineEdit("小熊")
        email_layout.addRow("发件人名称:", self.sender_name_input)
        
        self.sender_input = QLineEdit("1263083401@qq.com")
        email_layout.addRow("发件人邮箱:", self.sender_input)
        
        self.password_input = QLineEdit("lozxaplbufplbacg")
        self.password_input.setEchoMode(QLineEdit.Password)
        email_layout.addRow("邮箱授权码:", self.password_input)
        
        # 收件人设置
        self.receivers_input = QLineEdit("xingranna@gmail.com")
        email_layout.addRow("收件人邮箱:", self.receivers_input)
        
        layout.addWidget(email_group)
        
        # 创建按钮区域
        button_layout = QHBoxLayout()
        
        # 保存设置按钮
        self.save_settings_button = QPushButton("保存设置")
        self.save_settings_button.setObjectName("secondary")
        self.save_settings_button.clicked.connect(self.save_settings)
        button_layout.addWidget(self.save_settings_button)
        
        # 测试邮箱按钮
        self.test_email_button = QPushButton("测试邮箱")
        self.test_email_button.clicked.connect(self.test_email)
        button_layout.addWidget(self.test_email_button)
        
        layout.addLayout(button_layout)
        layout.addStretch(1)
    
    def log(self, message):
        self.log_text.append(message)
        self.statusBar.showMessage(message)
    
    def fetch_contribution(self):
        gitee_url = self.url_input.text().strip()
        if not gitee_url:
            QMessageBox.warning(self, "警告", "请输入有效的Gitee URL")
            return
        
        # 禁用按钮，防止重复点击
        self.fetch_button.setEnabled(False)
        self.send_button.setEnabled(False)
        self.save_button.setEnabled(False)
        
        # 清空日志
        self.log_text.clear()
        self.log("开始获取贡献图表...")
        
        # 创建并启动工作线程
        self.worker = WorkerThread(gitee_url)
        self.worker.update_signal.connect(self.log)
        self.worker.image_signal.connect(self.update_image)
        self.worker.finished_signal.connect(self.process_finished)
        self.worker.progress_signal.connect(self.update_progress)
        self.worker.start()
    
    def send_email(self):
        if not self.img_data:
            QMessageBox.warning(self, "警告", "请先获取贡献图表")
            return
        
        # 获取邮箱配置
        email_config = self.get_email_config()
        if not email_config:
            return
        
        # 禁用按钮，防止重复点击
        self.fetch_button.setEnabled(False)
        self.send_button.setEnabled(False)
        self.save_button.setEnabled(False)
        
        # 清空日志
        self.log_text.clear()
        self.log("开始发送邮件...")
        
        # 创建并启动工作线程
        self.worker = WorkerThread(self.url_input.text().strip(), email_config)
        self.worker.update_signal.connect(self.log)
        self.worker.image_signal.connect(self.update_image)
        self.worker.finished_signal.connect(self.process_finished)
        self.worker.progress_signal.connect(self.update_progress)
        self.worker.start()
    
    def save_image(self):
        if not self.img_data:
            QMessageBox.warning(self, "警告", "请先获取贡献图表")
            return
        
        # 打开文件对话框
        file_path, _ = QFileDialog.getSaveFileName(self, "保存图像", "contribution_box.png", "PNG图像 (*.png)")
        if file_path:
            try:
                with open(file_path, 'wb') as f:
                    f.write(self.img_data)
                self.log(f"图像已保存到: {file_path}")
                QMessageBox.information(self, "成功", f"图像已保存到: {file_path}")
            except Exception as e:
                self.log(f"保存图像失败: {str(e)}")
                QMessageBox.critical(self, "错误", f"保存图像失败: {str(e)}")
    
    def update_image(self, img_data):
        self.img_data = img_data
        
        # 将字节数据转换为QPixmap
        pixmap = QPixmap()
        pixmap.loadFromData(img_data)
        
        # 调整图像大小以适应标签
        pixmap = pixmap.scaled(self.image_label.width(), self.image_label.height(), 
                              Qt.KeepAspectRatio, Qt.SmoothTransformation)
        
        # 显示图像
        self.image_label.setPixmap(pixmap)
    
    def process_finished(self, success, message):
        # 重新启用按钮
        self.fetch_button.setEnabled(True)
        
        if success:
            self.send_button.setEnabled(True)
            self.save_button.setEnabled(True)
            self.log(message)
            self.statusBar.showMessage("就绪")
        else:
            self.log(message)
            QMessageBox.warning(self, "警告", message)
            self.statusBar.showMessage("发生错误")
    
    def update_progress(self, value):
        self.progress_bar.setValue(value)
    
    def get_email_config(self):
        mail_host = self.mail_host_input.text().strip()
        mail_port = self.mail_port_input.text().strip()
        sender_name = self.sender_name_input.text().strip()
        sender = self.sender_input.text().strip()
        password = self.password_input.text().strip()
        receivers = self.receivers_input.text().strip()
        
        # 验证必填字段
        if not all([mail_host, mail_port, sender, password, receivers]):
            QMessageBox.warning(self, "警告", "请填写所有必填的邮箱设置")
            return None
        
        # 验证端口号
        try:
            mail_port = int(mail_port)
        except ValueError:
            QMessageBox.warning(self, "警告", "端口号必须是数字")
            return None
        
        return {
            'mail_host': mail_host,
            'mail_port': mail_port,
            'sender_name': sender_name,
            'sender': sender,
            'password': password,
            'receivers': receivers
        }
    
    def save_settings(self):
        email_config = self.get_email_config()
        if email_config:
            QMessageBox.information(self, "成功", "设置已保存")
    
    def test_email(self):
        email_config = self.get_email_config()
        if not email_config:
            return
        
        try:
            self.log("正在测试邮箱连接...")
            
            # 尝试连接到邮箱服务器
            with smtplib.SMTP(email_config['mail_host'], email_config['mail_port']) as server:
                server.starttls()
                server.login(email_config['sender'], email_config['password'])
                self.log("邮箱连接测试成功！")
                QMessageBox.information(self, "成功", "邮箱连接测试成功！")
        except Exception as e:
            error_msg = f"邮箱连接测试失败: {str(e)}"
            self.log(error_msg)
            QMessageBox.critical(self, "错误", error_msg)

# 应用入口
if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())